<template>
  <render />
</template>
<script setup lang="jsx">
import { defineProps, onBeforeMount, ref, h, defineEmits } from "vue";
// 1.引入组件库
import { components, parsers } from "@/components/index.js";


/**
 * 渲染引擎: 浏览器渲染和显示html,css,js内容的
 * 将json协议渲染成ui界面
 *
 定义vnode树形数据结构，渲染函数逐级解析vnode树，最终调用渲染组件的render函数进行渲染

1.封装渲染引擎工作流程:

  1.引入组件库，进行遍历解析json,生成一个骨架填充组件 （深度优化遍历数组）
  2.嵌套组件处理依赖 （处理父子，兄弟之间的关系，拆分开渲染）
   有子组件递归， 没有直接渲染单个组件
  3.全局配置解析:右侧可以配置每一个组件

 2.渲染组件
*/

const props = defineProps({
  jsonSchema: Object, // 配置协议
  addNode: { type: String, default: "" }, // 新增拖入主界面的节点
});

const page = ref({});
const emit = defineEmits(["pickType"]);

onBeforeMount(() => {
  init();
});

const render = () => {
  /* ---- 可拓展启动前的参数 ----  */
  return renderRoot(h); // 渲染根逻辑
};

// 提取页面参数,初始化
function init() {
  page.value = props.jsonSchema || {}; // 渲染引擎每次只能渲染一个页面
}

// 1.页面容器 渲染根节点 - 代表整个的页面，配置
function renderRoot() {
  let _page = page.value;

  return <div class="root">{renderComponents(h, _page)}</div>;
}

/**
 *2.渲染组件 - 处理依赖 (递归)
  section 接收一个块，不感知是哪一个层级，统一逻辑处理
 */
function renderComponents(h, section) {
  // 是否有子节点
  let _children = null;

  if (section.children) {
    // 层级渲染,插入布局组件
    _children = renderChildren(h, section);
  }
  // 渲染组件
  return startRnder(h, section, _children);
}

// 2.1  子组件的拆分： 遍历包含兄弟&子节点
function renderChildren(h, section) {
  let _nodeArr = section.children || [].concat(section);

  return _nodeArr.map((item) => {
    return renderComponents(h, item);
  });
}

// 3.开始渲染
function startRnder(h, section, _children) {
  const _type = section.type; // 组件类型
  const renderMod = parsers[_type]; // 当前组件的json 比如parser-button.js（用类型来映射换当前组件的外壳）

  if (renderMod) {
    const _props = { onDrop: handleDrop };

    // 通过 h 函数动态创建虚拟节点（VNode）
    return h(renderMod.render(h, section, _children, _props), {
      onclick: (e) => {
        e.stopPropagation();
        emit("pickType", _type, section.id);
      },
    });
  }
  return null;
}

// 以下为配置系统统一化处理逻辑
// 拖拽组件经过触发
function handleDragOver() {}

// 拖拽添加部分： 拖拽组件松手
function handleDrop(event, vm) {
  const _json = vm.jsonSchema;

  if (_json && _json.type === "cContainer") {
    if (!_json.children) {
      _json = { ..._json, children: [] };
    }
    _json.children.push({
      type: props.addNode,
    });
  }
}
</script>

<!-- 
type: "cContainer",
children: [
  {
    type: "cbutton",
  },
  {
    type: "cContainer",
    children: [
      {
        type: "cInput",
      },
      {
        type: "cbutton",
      },
    ],
  },
],
}, -->
